// $ANTLR 3.0.1 /data/workspace/silibrina-snooker/src/main/antlr/Expression.g 2008-04-25 02:05:00

package blms.util.expression;

import java.util.Set;

import org.antlr.runtime.BitSet;
import org.antlr.runtime.NoViableAltException;
import org.antlr.runtime.Parser;
import org.antlr.runtime.ParserRuleReturnScope;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
import org.antlr.runtime.TokenStream;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeAdaptor;
import org.antlr.runtime.tree.RewriteRuleSubtreeStream;
import org.antlr.runtime.tree.RewriteRuleTokenStream;
import org.antlr.runtime.tree.TreeAdaptor;

import blms.exception.UnknownVariableException;

public class ExpressionParser extends Parser {
	public static final String[] tokenNames = new String[] { "<invalid>",
			"<EOR>", "<DOWN>", "<UP>", "NEWLINE", "INT", "ID", "WS", "'+'",
			"'-'", "'*'", "'/'", "'('", "')'" };
	public static final int WS = 7;
	public static final int NEWLINE = 4;
	public static final int INT = 5;
	public static final int ID = 6;
	public static final int EOF = -1;

	public ExpressionParser(final TokenStream input) {
		super(input);
	}

	protected TreeAdaptor adaptor = new CommonTreeAdaptor();

	public void setTreeAdaptor(final TreeAdaptor adaptor) {
		this.adaptor = adaptor;
	}

	public TreeAdaptor getTreeAdaptor() {
		return adaptor;
	}

	@Override
	public String[] getTokenNames() {
		return tokenNames;
	}

	@Override
	public String getGrammarFileName() {
		return "/data/workspace/silibrina-snooker/src/main/antlr/Expression.g";
	}

	/** Set of variable names. */
	private Set<String> variables = new java.util.HashSet<String>();

	/** Set up an parser with a token stream; and a set of variables names. */
	public ExpressionParser(final TokenStream input, final Set<String> variables) {
		this(input);
		this.variables = variables;
	}

	public static class prog_return extends ParserRuleReturnScope {
		CommonTree tree;

		@Override
		public Object getTree() {
			return tree;
		}
	};

	// $ANTLR start prog
	// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:24:1: prog
	// : stat ;
	public final prog_return prog() throws RecognitionException {
		final prog_return retval = new prog_return();
		retval.start = input.LT(1);

		CommonTree root_0 = null;

		stat_return stat1 = null;

		try {
			// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:24:5:
			// ( stat )
			// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:24:8:
			// stat
			{
				root_0 = (CommonTree) adaptor.nil();

				pushFollow(FOLLOW_stat_in_prog45);
				stat1 = stat();
				_fsp--;

				adaptor.addChild(root_0, stat1.getTree());

			}

			retval.stop = input.LT(-1);

			retval.tree = (CommonTree) adaptor.rulePostProcessing(root_0);
			adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);

		} catch (final RecognitionException re) {
			reportError(re);
			recover(input, re);
		} finally {
		}
		return retval;
	}

	// $ANTLR end prog

	public static class stat_return extends ParserRuleReturnScope {
		CommonTree tree;

		@Override
		public Object getTree() {
			return tree;
		}
	};

	// $ANTLR start stat
	// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:26:1: stat
	// : ( expr NEWLINE -> expr | NEWLINE ->);
	public final stat_return stat() throws RecognitionException {
		final stat_return retval = new stat_return();
		retval.start = input.LT(1);

		CommonTree root_0 = null;

		Token NEWLINE3 = null;
		Token NEWLINE4 = null;
		expr_return expr2 = null;

		final RewriteRuleTokenStream stream_NEWLINE = new RewriteRuleTokenStream(
				adaptor, "token NEWLINE");
		final RewriteRuleSubtreeStream stream_expr = new RewriteRuleSubtreeStream(
				adaptor, "rule expr");
		try {
			// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:26:5:
			// ( expr NEWLINE -> expr | NEWLINE ->)
			int alt1 = 2;
			final int LA1_0 = input.LA(1);

			if ((((LA1_0 >= INT) && (LA1_0 <= ID)) || (LA1_0 == 12))) {
				alt1 = 1;
			} else if ((LA1_0 == NEWLINE)) {
				alt1 = 2;
			} else {
				final NoViableAltException nvae = new NoViableAltException(
						"26:1: stat : ( expr NEWLINE -> expr | NEWLINE ->);",
						1, 0, input);

				throw nvae;
			}
			switch (alt1) {
			case 1:
				// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:26:9:
				// expr NEWLINE
			{
				pushFollow(FOLLOW_expr_in_stat55);
				expr2 = expr();
				_fsp--;

				stream_expr.add(expr2.getTree());
				NEWLINE3 = input.LT(1);
				match(input, NEWLINE, FOLLOW_NEWLINE_in_stat57);
				stream_NEWLINE.add(NEWLINE3);

				// AST REWRITE
				// elements: expr
				// token labels:
				// rule labels: retval
				// token list labels:
				// rule list labels:
				retval.tree = root_0;
				final RewriteRuleSubtreeStream stream_retval = new RewriteRuleSubtreeStream(
						adaptor, "token retval", retval != null ? retval.tree
								: null);

				root_0 = (CommonTree) adaptor.nil();
				// 26:29: -> expr
				{
					adaptor.addChild(root_0, stream_expr.next());

				}

			}
				break;
			case 2:
				// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:27:9:
				// NEWLINE
			{
				NEWLINE4 = input.LT(1);
				match(input, NEWLINE, FOLLOW_NEWLINE_in_stat78);
				stream_NEWLINE.add(NEWLINE4);

				// AST REWRITE
				// elements:
				// token labels:
				// rule labels: retval
				// token list labels:
				// rule list labels:
				retval.tree = root_0;
				final RewriteRuleSubtreeStream stream_retval = new RewriteRuleSubtreeStream(
						adaptor, "token retval", retval != null ? retval.tree
								: null);

				root_0 = (CommonTree) adaptor.nil();
				// 27:29: ->
				{
					root_0 = null;
				}

			}
				break;

			}
			retval.stop = input.LT(-1);

			retval.tree = (CommonTree) adaptor.rulePostProcessing(root_0);
			adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);

		} catch (final RecognitionException re) {
			reportError(re);
			recover(input, re);
		} finally {
		}
		return retval;
	}

	// $ANTLR end stat

	public static class expr_return extends ParserRuleReturnScope {
		CommonTree tree;

		@Override
		public Object getTree() {
			return tree;
		}
	};

	// $ANTLR start expr
	// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:30:1: expr
	// : multExpr ( ( '+' | '-' ) multExpr )* ;
	public final expr_return expr() throws RecognitionException {
		final expr_return retval = new expr_return();
		retval.start = input.LT(1);

		CommonTree root_0 = null;

		Token char_literal6 = null;
		Token char_literal7 = null;
		multExpr_return multExpr5 = null;

		multExpr_return multExpr8 = null;

		CommonTree char_literal6_tree = null;
		CommonTree char_literal7_tree = null;

		try {
			// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:30:5:
			// ( multExpr ( ( '+' | '-' ) multExpr )* )
			// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:30:9:
			// multExpr ( ( '+' | '-' ) multExpr )*
			{
				root_0 = (CommonTree) adaptor.nil();

				pushFollow(FOLLOW_multExpr_in_expr106);
				multExpr5 = multExpr();
				_fsp--;

				adaptor.addChild(root_0, multExpr5.getTree());
				// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:30:18:
				// ( ( '+' | '-' ) multExpr )*
				loop3: do {
					int alt3 = 2;
					final int LA3_0 = input.LA(1);

					if ((((LA3_0 >= 8) && (LA3_0 <= 9)))) {
						alt3 = 1;
					}

					switch (alt3) {
					case 1:
						// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:30:19:
						// ( '+' | '-' ) multExpr
					{
						// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:30:19:
						// ( '+' | '-' )
						int alt2 = 2;
						final int LA2_0 = input.LA(1);

						if ((LA2_0 == 8)) {
							alt2 = 1;
						} else if ((LA2_0 == 9)) {
							alt2 = 2;
						} else {
							final NoViableAltException nvae = new NoViableAltException(
									"30:19: ( '+' | '-' )", 2, 0, input);

							throw nvae;
						}
						switch (alt2) {
						case 1:
							// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:30:20:
							// '+'
						{
							char_literal6 = input.LT(1);
							match(input, 8, FOLLOW_8_in_expr110);
							char_literal6_tree = (CommonTree) adaptor
									.create(char_literal6);
							root_0 = (CommonTree) adaptor.becomeRoot(
									char_literal6_tree, root_0);

						}
							break;
						case 2:
							// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:30:25:
							// '-'
						{
							char_literal7 = input.LT(1);
							match(input, 9, FOLLOW_9_in_expr113);
							char_literal7_tree = (CommonTree) adaptor
									.create(char_literal7);
							root_0 = (CommonTree) adaptor.becomeRoot(
									char_literal7_tree, root_0);

						}
							break;

						}

						pushFollow(FOLLOW_multExpr_in_expr117);
						multExpr8 = multExpr();
						_fsp--;

						adaptor.addChild(root_0, multExpr8.getTree());

					}
						break;

					default:
						break loop3;
					}
				} while (true);

			}

			retval.stop = input.LT(-1);

			retval.tree = (CommonTree) adaptor.rulePostProcessing(root_0);
			adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);

		} catch (final RecognitionException re) {
			reportError(re);
			recover(input, re);
		} finally {
		}
		return retval;
	}

	// $ANTLR end expr

	public static class multExpr_return extends ParserRuleReturnScope {
		CommonTree tree;

		@Override
		public Object getTree() {
			return tree;
		}
	};

	// $ANTLR start multExpr
	// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:33:1:
	// multExpr : atom ( ( '*' | '/' ) atom )* ;
	public final multExpr_return multExpr() throws RecognitionException {
		final multExpr_return retval = new multExpr_return();
		retval.start = input.LT(1);

		CommonTree root_0 = null;

		Token char_literal10 = null;
		Token char_literal11 = null;
		atom_return atom9 = null;

		atom_return atom12 = null;

		CommonTree char_literal10_tree = null;
		CommonTree char_literal11_tree = null;

		try {
			// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:34:5:
			// ( atom ( ( '*' | '/' ) atom )* )
			// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:34:9:
			// atom ( ( '*' | '/' ) atom )*
			{
				root_0 = (CommonTree) adaptor.nil();

				pushFollow(FOLLOW_atom_in_multExpr139);
				atom9 = atom();
				_fsp--;

				adaptor.addChild(root_0, atom9.getTree());
				// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:34:14:
				// ( ( '*' | '/' ) atom )*
				loop5: do {
					int alt5 = 2;
					final int LA5_0 = input.LA(1);

					if ((((LA5_0 >= 10) && (LA5_0 <= 11)))) {
						alt5 = 1;
					}

					switch (alt5) {
					case 1:
						// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:34:15:
						// ( '*' | '/' ) atom
					{
						// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:34:15:
						// ( '*' | '/' )
						int alt4 = 2;
						final int LA4_0 = input.LA(1);

						if ((LA4_0 == 10)) {
							alt4 = 1;
						} else if ((LA4_0 == 11)) {
							alt4 = 2;
						} else {
							final NoViableAltException nvae = new NoViableAltException(
									"34:15: ( '*' | '/' )", 4, 0, input);

							throw nvae;
						}
						switch (alt4) {
						case 1:
							// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:34:16:
							// '*'
						{
							char_literal10 = input.LT(1);
							match(input, 10, FOLLOW_10_in_multExpr143);
							char_literal10_tree = (CommonTree) adaptor
									.create(char_literal10);
							root_0 = (CommonTree) adaptor.becomeRoot(
									char_literal10_tree, root_0);

						}
							break;
						case 2:
							// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:34:21:
							// '/'
						{
							char_literal11 = input.LT(1);
							match(input, 11, FOLLOW_11_in_multExpr146);
							char_literal11_tree = (CommonTree) adaptor
									.create(char_literal11);
							root_0 = (CommonTree) adaptor.becomeRoot(
									char_literal11_tree, root_0);

						}
							break;

						}

						pushFollow(FOLLOW_atom_in_multExpr150);
						atom12 = atom();
						_fsp--;

						adaptor.addChild(root_0, atom12.getTree());

					}
						break;

					default:
						break loop5;
					}
				} while (true);

			}

			retval.stop = input.LT(-1);

			retval.tree = (CommonTree) adaptor.rulePostProcessing(root_0);
			adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);

		} catch (final RecognitionException re) {
			reportError(re);
			recover(input, re);
		} finally {
		}
		return retval;
	}

	// $ANTLR end multExpr

	public static class atom_return extends ParserRuleReturnScope {
		CommonTree tree;

		@Override
		public Object getTree() {
			return tree;
		}
	};

	// $ANTLR start atom
	// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:37:1: atom
	// : ( INT | ID | '(' expr ')' );
	public final atom_return atom() throws RecognitionException {
		final atom_return retval = new atom_return();
		retval.start = input.LT(1);

		CommonTree root_0 = null;

		Token INT13 = null;
		Token ID14 = null;
		Token char_literal15 = null;
		Token char_literal17 = null;
		expr_return expr16 = null;

		CommonTree INT13_tree = null;
		CommonTree ID14_tree = null;
		try {
			// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:37:5:
			// ( INT | ID | '(' expr ')' )
			int alt6 = 3;
			switch (input.LA(1)) {
			case INT: {
				alt6 = 1;
			}
				break;
			case ID: {
				alt6 = 2;
			}
				break;
			case 12: {
				alt6 = 3;
			}
				break;
			default:
				final NoViableAltException nvae = new NoViableAltException(
						"37:1: atom : ( INT | ID | '(' expr ')' );", 6, 0,
						input);

				throw nvae;
			}

			switch (alt6) {
			case 1:
				// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:37:9:
				// INT
			{
				root_0 = (CommonTree) adaptor.nil();

				INT13 = input.LT(1);
				match(input, INT, FOLLOW_INT_in_atom166);
				INT13_tree = (CommonTree) adaptor.create(INT13);
				adaptor.addChild(root_0, INT13_tree);

			}
				break;
			case 2:
				// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:38:9:
				// ID
			{
				root_0 = (CommonTree) adaptor.nil();

				ID14 = input.LT(1);
				match(input, ID, FOLLOW_ID_in_atom176);
				ID14_tree = (CommonTree) adaptor.create(ID14);
				adaptor.addChild(root_0, ID14_tree);

				final String name = ID14.getText();
				if (!variables.contains(name)) {
					throw new UnknownVariableException();
				}

			}
				break;
			case 3:
				// /data/workspace/silibrina-snooker/src/main/antlr/Expression.g:45:9:
				// '(' expr ')'
			{
				root_0 = (CommonTree) adaptor.nil();

				char_literal15 = input.LT(1);
				match(input, 12, FOLLOW_12_in_atom197);
				pushFollow(FOLLOW_expr_in_atom200);
				expr16 = expr();
				_fsp--;

				adaptor.addChild(root_0, expr16.getTree());
				char_literal17 = input.LT(1);
				match(input, 13, FOLLOW_13_in_atom202);

			}
				break;

			}
			retval.stop = input.LT(-1);

			retval.tree = (CommonTree) adaptor.rulePostProcessing(root_0);
			adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);

		} catch (final RecognitionException re) {
			reportError(re);
			recover(input, re);
		} finally {
		}
		return retval;
	}

	// $ANTLR end atom

	public static final BitSet FOLLOW_stat_in_prog45 = new BitSet(
			new long[] { 0x0000000000000002L });
	public static final BitSet FOLLOW_expr_in_stat55 = new BitSet(
			new long[] { 0x0000000000000010L });
	public static final BitSet FOLLOW_NEWLINE_in_stat57 = new BitSet(
			new long[] { 0x0000000000000002L });
	public static final BitSet FOLLOW_NEWLINE_in_stat78 = new BitSet(
			new long[] { 0x0000000000000002L });
	public static final BitSet FOLLOW_multExpr_in_expr106 = new BitSet(
			new long[] { 0x0000000000000302L });
	public static final BitSet FOLLOW_8_in_expr110 = new BitSet(
			new long[] { 0x0000000000001060L });
	public static final BitSet FOLLOW_9_in_expr113 = new BitSet(
			new long[] { 0x0000000000001060L });
	public static final BitSet FOLLOW_multExpr_in_expr117 = new BitSet(
			new long[] { 0x0000000000000302L });
	public static final BitSet FOLLOW_atom_in_multExpr139 = new BitSet(
			new long[] { 0x0000000000000C02L });
	public static final BitSet FOLLOW_10_in_multExpr143 = new BitSet(
			new long[] { 0x0000000000001060L });
	public static final BitSet FOLLOW_11_in_multExpr146 = new BitSet(
			new long[] { 0x0000000000001060L });
	public static final BitSet FOLLOW_atom_in_multExpr150 = new BitSet(
			new long[] { 0x0000000000000C02L });
	public static final BitSet FOLLOW_INT_in_atom166 = new BitSet(
			new long[] { 0x0000000000000002L });
	public static final BitSet FOLLOW_ID_in_atom176 = new BitSet(
			new long[] { 0x0000000000000002L });
	public static final BitSet FOLLOW_12_in_atom197 = new BitSet(
			new long[] { 0x0000000000001060L });
	public static final BitSet FOLLOW_expr_in_atom200 = new BitSet(
			new long[] { 0x0000000000002000L });
	public static final BitSet FOLLOW_13_in_atom202 = new BitSet(
			new long[] { 0x0000000000000002L });

}